﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://wpfimageviewer.codeplex.com
using System;
using System.Linq;
using System.Collections.Generic;
using System.Drawing;
using BrainTechLLC;
using BrainTechLLC.ThreadSafeObjects;
using ImageAppDataModels;
using ImageAppViewModels;
using System.Windows.Data;

namespace WpfImageDuplicates
{
    /// <summary>
    /// This class handles a collection of thumbnails and takes
    /// care of work suck as preloading thumbnails, cleaning up non-visible thumbs,
    /// offering a quick lookup of thumbnail view by file name, etc
    /// </summary>
    public class ThumbnailImageCollectionHandler : IThumbnailImageCollectionHandler
    {
        public FileImageViewModel MasterImage;
        public PreLoader<Bitmap> ThumbPreloader;
        public ThumbnailCleanup ThumbCleanup;

        /// <summary>
        /// Stores a cached list of all thumbnail views
        /// </summary>        
        public List<ThumbnailView> ThumbnailViewsLast = new List<ThumbnailView>();

        public ThreadSafeLookup<ThumbnailView, ThumbnailView> NonDirtyThumbs = new ThreadSafeLookup<ThumbnailView, ThumbnailView>();

        /// <summary>
        /// Looking of thumbnail view by file name (full path)
        /// </summary>
        public ThreadSafeLookup<string, ThumbnailView> _thumbsByFileName = new ThreadSafeLookup<string, ThumbnailView>();
        public SimpleTimer _initTimer;

        public ImageCollectionView _parentView;

        public int ThumbCount
        {
            get { return _thumbsByFileName.Count; }
        }

        /// <summary>
        /// Parent Image Collection View
        /// </summary>
        public ImageCollectionView ParentView
        {
            get { return _parentView; }
        }

        /// <summary>
        /// Parent Image Collection View's FileImageCollectionViewModel
        /// </summary>
        public FileImageCollectionViewModel CollectionViewModel
        {
            get { return _parentView == null ? null : _parentView._vm; }
        }

        public ThumbnailImageCollectionHandler(ImageCollectionView parentView)
        {
            _parentView = parentView;
            ThumbCleanup = new ThumbnailCleanup(this);
            _initTimer = new SimpleTimer(100, 100, timer => StartThumbPreloader(timer));
        }

        protected RunInitializationResult StartThumbPreloader(SimpleTimer timer)
        {
            if (Settings.Values == null)
                return RunInitializationResult.ContinueTimer;

            ThumbPreloader = new PreLoader<Bitmap>(Settings.Values.ThumbPreloadThreads, System.Threading.ThreadPriority.Normal, true);
            // ThumbPreloader = new PreLoader<Bitmap>(Settings.Values.ThumbPreloadThreads, System.Threading.ThreadPriority.AboveNormal, true);
            ThumbPreloader.Start();
            return RunInitializationResult.StopTimer;
        }

        //public void CleanThumbnailViews()
        //{
        //    var all = _thumbsByFileName.AllKeyValuePairs;
        //    for (int n = 0; n < all.Count; n++)
        //    {
        //        var tv = all[n];
        //        if (tv.Value.Parent == null || tv.Value._vm == null)
        //        {
        //            ThumbnailViewsLast.Remove(tv.Value);
        //            NonDirtyThumbs.Remove(tv.Value);
        //            _thumbsByFileName.Remove(tv);
        //        }
        //    }
        //}

        /// <summary>
        /// Returns a list of all thumbnail views.  The list may be a cached list and should
        /// be copied before performing any list modifications
        /// </summary>
        /// <returns></returns>
        public List<ThumbnailView> GetAllThumbnailViews()
        {
            if (_thumbsByFileName.Count != ThumbnailViewsLast.Count)
            {
                try
                {
                    lock (_parentView._lockObject)
                    {
                        if (_thumbsByFileName.Count != ThumbnailViewsLast.Count)
                        {
                            ThumbnailViewsLast = _thumbsByFileName.AllItems;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
            return ThumbnailViewsLast;
        }


        public void MarkThumbnailFileNameLocationChanged()
        {
            // THIS IS PROBABLY REALLY EXPENSIVE
            var all = GetAllThumbnailViews();

            for (int n = all.Count - 1; n >= 0; n--)
            {
                var thumb = all[n];
                thumb.SetFileNamePosition();
            }
        }

        public void MarkThumbImagesDirty()
        {
            if (NonDirtyThumbs.Count > 0)
            {
                List<ThumbnailView> list = NonDirtyThumbs.GetAllItemsAndClear();
                try
                {
                    list.ForEachBackwards((i, thumb) => thumb.MarkThumbImageDirty());
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
            //GetAllThumbnailViews().ForEachBackwards((i, thumb) => thumb.MarkThumbImageDirty());
        }

        public void MarkThumbsDirty()
        {
            if (NonDirtyThumbs.Count > 0)
            {
                List<ThumbnailView> list = NonDirtyThumbs.GetAllItemsAndClear();
                try
                {
                    list.ForEachBackwards((i, thumb) => thumb.MarkThumbDirty());
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
            //GetAllThumbnailViews().ForEachBackwards((i, thumb) => thumb.MarkThumbDirty());
        }

        public void ForceRemoveThumbView(IFileImage image)
        {
            if (_thumbsByFileName.Remove(image.FileName))
            {
            }
        }

        public ThumbnailView FindThumbView(IFileImage image)
        {
            return _thumbsByFileName[image.FileName];
        }

        public ThumbnailView FindThumbView(string fileName)
        {
            return _thumbsByFileName[fileName];
        }

        public void WantResize(ThumbnailView originating, int width, int height)
        {
            bool wasSelected = _parentView.IsSelected(originating);
            ThumbnailView modified = null;
            if (!wasSelected)
            {
                modified = FindThumbView(originating.FileImageViewModel.FileImage);
                modified.Resize(width, height);
            }

            _parentView.DoForSelected((item) =>
            {
                var thumb = FindThumbView(item.FileImage);
                if (!wasSelected && thumb != modified)
                {
                    thumb.Resize(width, height);
                }
            });
        }

        public void WantResizeDelete(ThumbnailView originating, int width, int height)
        {
            bool wasSelected = _parentView.IsSelected(originating);
            ThumbnailView modified = null;            
            if (!wasSelected)
            {
                modified = FindThumbView(originating.FileImageViewModel.FileImage);
                // TEST THIS
                if (modified != null)
                {
                    var resizeInfo = new ResizeInfo() { f1 = modified._vm.Item, width = width, height = height, done = false };                    
                    modified.ResizeDelete(width, height, resizeInfo);
                }
            }

            _parentView.DoForSelected((item) =>
            {
                var thumb = FindThumbView(item.FileImage);
                if (thumb != null && thumb != modified)
                {
                    var resizeInfo = new ResizeInfo() { f1 = item.Item, width = width, height = height, done = false };
                    thumb.ResizeDelete(width, height, resizeInfo);
                }
            });
        }

        public void WantRotateSelectedCounterClockwise(ThumbnailView originating)
        {
            bool wasSelected = _parentView.IsSelected(originating);
            ThumbnailView modified = null;
            if (!wasSelected)
            {
                modified = FindThumbView(originating.FileImageViewModel.FileImage);
                modified.Rotate(System.Windows.Media.Imaging.Rotation.Rotate90, false);
            }

            _parentView.DoForSelected((item) =>
            {
                if (modified == null || item != modified.FileImageViewModel)
                {
                    var thumbView = FindThumbView(item.FileImage);
                    if (thumbView != null)
                    {
                        thumbView.Rotate(System.Windows.Media.Imaging.Rotation.Rotate90, false);
                    }
                }
            });
        }

        public void WantRotateSelectedClockwise(ThumbnailView originating)
        {
            bool wasSelected = _parentView.IsSelected(originating);
            ThumbnailView modified = null;
            if (!wasSelected)
            {
                modified = FindThumbView(originating.FileImageViewModel.FileImage);
                modified.Rotate(System.Windows.Media.Imaging.Rotation.Rotate90, true);
            }

            _parentView.DoForSelected((item) =>
            {
                if (modified == null || item != modified.FileImageViewModel)
                {
                    var thumb = FindThumbView(item.FileImage);
                    if (thumb != null)
                    {
                        thumb.Rotate(System.Windows.Media.Imaging.Rotation.Rotate90, true);
                    }
                }
            });
        }

        public void WantDeleteSelected(ThumbnailView originating)
        {
            bool wasSelected = _parentView.IsSelected(originating);
            ThumbnailView modified = null;
            FileImageViewModel vmSaved = null;
            if (!wasSelected)
            {
                modified = FindThumbView(originating.FileImageViewModel.FileImage);
                vmSaved = modified.FileImageViewModel;
                modified.FileImageViewModel.Delete();
            }

            _parentView.DoForSelected((item) =>
            {
                if (vmSaved != item)
                {
                    item.Delete();
                }
            });
        }


    }
}
